package com.thwj.project.app.api;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.thwj.common.exception.ServiceException;
import com.thwj.framework.config.properties.OssProperties;
import com.thwj.framework.web.domain.R;
import com.thwj.project.app.api.vo.AppFileUploadToken;
import com.thwj.project.system.domain.SysOss;
import com.thwj.project.system.service.ISysOssService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.List;

/**
 * oss 文件上传Controller
 *
 * @author 可乐
 * @date 2022-03-20
 */
@Slf4j
@RestController
@RequestMapping("app/file/oss")
@Api(tags = "app 小程序文件上传")
public class AppFileController {
    @Autowired
    private OssProperties ossConfig;
    @Autowired
    private DefaultAcsClient acsClient;
    @Autowired
    private OSS ossClient;
    @Autowired
    private ISysOssService sysOssService;

    /**
     * 阿里云小程序上传获取签名
     */
    @ApiOperation(value = "创建文件上传token",notes = "https://help.aliyun.com/document_detail/120092.htm?spm=a2c4g.100624.0.0.6fcd351eeWB3Ny#section-iy3-bfe-7mn或者https://blog.csdn.net/qq_45364616/article/details/124942510")
    @PostMapping("/createOssUploadToken")
    public R<AppFileUploadToken> createOssUploadToken() {
        // 填写步骤3获取的角色ARN。
        String roleArn = "acs:ram::1778328836489936:role/daya";
        // 自定义角色会话名称，用来区分不同的令牌，例如可填写为SessionTest。
        String roleSessionName = "daya";
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket下的src目录上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集，即仅允许将文件上传至目标存储空间examplebucket下的src目录。
        // 如果policy为空，则用户将获得该角色下所有权限。
        String policy = "{\n" +
                "    \"Version\": \"1\",\n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Effect\": \"Allow\",\n" +
                "            \"Action\": \"oss:PutObject\",\n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:daya-dev/app/*\",\n" +
                "                \"acs:oss:*:*:daya-dev/admin/*\"\n" +
                "            ]\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        // 设置临时访问凭证的有效时间为3600秒。
        Long durationSeconds = 3600L;
        try {

            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            // 适用于Java SDK 3.12.0以下版本。
            //request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(policy);
            request.setDurationSeconds(durationSeconds);
            final AssumeRoleResponse response = acsClient.getAcsResponse(request);

            AppFileUploadToken appFileUploadToken = new AppFileUploadToken();
            appFileUploadToken.setAccessKeyId(response.getCredentials().getAccessKeyId());
            appFileUploadToken.setAccessKeySecret(response.getCredentials().getAccessKeySecret());
            appFileUploadToken.setStsToken(response.getCredentials().getSecurityToken());
            appFileUploadToken.setRegion("oss-cn-hangzhou");
            appFileUploadToken.setBucket(ossConfig.getBucketName());
            appFileUploadToken.setDomain(ossConfig.getDomain());

            return R.data(appFileUploadToken);
        } catch (ServerException e) {
            log.error("阿里云sts生成异常 {}", e);
            throw new ServiceException("文件上传服务异常");
        } catch (com.aliyuncs.exceptions.ClientException e) {
            log.error("阿里云sts生成异常 {}", e);
            throw new ServiceException("文件上传服务异常");
        }
    }



    @ApiOperation(value = "微信小程序直传阿里云",notes = "https://help.aliyun.com/document_detail/92883.html?spm=5176.8466032.bucket.dpractice-file-wechat.78d41450YKuYmD")
    @PostMapping("/createOssUploadTokenV2")
    public R<AppFileUploadToken> createOssUploadTokenV2() {
        String host = "https://" + ossConfig.getBucketName() + "." + ossConfig.getEndpoint(); // host的格式为 bucketname.endpoint
        // callbackUrl为 上传回调服务器的URL，请将下面的IP和Port配置为您自己的真实信息。
        String dir = "app/user/"; // 用户上传文件时指定的前缀。

        try {
            long expireTime = 30*60;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 20*1024*1024);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            AppFileUploadToken uploadToken = new AppFileUploadToken();
            uploadToken.setOSSAccessKeyId(ossConfig.getAccessKeyId());
            uploadToken.setPolicy(encodedPolicy);
            uploadToken.setSignature(postSignature);
            uploadToken.setHost(host);
            uploadToken.setDir(dir);
            uploadToken.setExpire(String.valueOf(expireEndTime / 1000));
            // 前端上传设置回调信息
//            JSONObject jasonCallback = new JSONObject();
//            jasonCallback.put("callbackUrl", ossConfig.getCallbackUrl());
//            jasonCallback.put("callbackBody",
//                    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
//            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
//            String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
//            uploadToken.setBase64CallbackBody(base64CallbackBody);
            return R.data(uploadToken);
        } catch (Exception e) {
            log.error("createOssUploadToken:请求异常 {}",e);
        } finally {
            ossClient.shutdown();
        }
        throw new ServiceException("图片上传服务异常");
    }

    /**
     * 阿里云小程序上传获取签名
     */
    @ApiOperation(value = "文件上传到自己服务器然后转发到oss",notes = "https://help.aliyun.com/document_detail/120092.htm?spm=a2c4g.100624.0.0.6fcd351eeWB3Ny#section-iy3-bfe-7mn或者https://blog.csdn.net/qq_45364616/article/details/124942510")
    @PostMapping("/uploadFile2Oss")
    public R<SysOss> uploadFile2Oss(@RequestParam("file") MultipartFile file, @RequestParam(value = "size", defaultValue = "5") int size) {
        SysOss sysOss=  sysOssService.addSysOsss(file,size);
        return R.data(sysOss);
    }

    /**
     * 阿里云小程序上传获取签名
     */
    @ApiOperation(value = "文件上传到自己服务器然后转发到oss",notes = "https://help.aliyun.com/document_detail/120092.htm?spm=a2c4g.100624.0.0.6fcd351eeWB3Ny#section-iy3-bfe-7mn或者https://blog.csdn.net/qq_45364616/article/details/124942510")
    @PostMapping("/uploadFileList2Oss")
    public R<List<SysOss>> uploadFileList2Oss(@RequestParam("file") MultipartFile[] file, @RequestParam(value = "size", defaultValue = "5") int size) {
        List<SysOss> sysOss =  sysOssService.insertSysOsss(file,size);
        return R.data(sysOss);
    }
}
